/***************************************************************************
 创建者: 华磊
 开始时间: 2018.8.14
 copyright: (C) 华友高科
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) 李文友 2017.5.8 类的具体实现代码编写

 ***************************************************************************
 *  @file x.h
 *  功能:
 *
 *                                                                         *
 ***************************************************************************/
#ifndef robotcontrol_H
#define robotcontrol_H

#include "domparser.h"
#include "globalDefine.h"
#include "GeneralDefine.h"
#include "ecattype.h"
#include <QMap>

//#include "vrepcontrol.h"
class EcatBusManager;
class EcatLog;
class RobotBase;
class EcatMasterBase;

class ModbusCom;
class CanbusCom;
class VrepControl;
class VrepObject;

//namespace hmigsoapnamespace{
//class RobotControl;
//}
//using namespace hmigsoapnamespace;
/**
 * @brief The RobotControl class ecat模块对外接口
 */
class RobotControl : public  DomParser
{
public:
    RobotControl();
    ~RobotControl();

public:
    int getVrepSimulationRobotId(int &robotIDOut);
    int getEncoderReceiverOutput(unsigned short &doOut);
    int getEncoderReceiverOutput(int aliasIn, unsigned short &doOut);//没加锁，可能coredump
    int setEncoderReceiverOutput_bit(int bitIndex, bool isHigh);
    int setEncoderReceiverOutput(unsigned short doIn);
    int setEncoderReceiverOutput(int aliasIn, unsigned short doIn);//没加锁，可能coredump
    int getEncoderReceiverData_iomodule(std::vector<EncoderReceiverData> &dataListReturn);
    int getEncoderReceiverData_iomodule(int aliasIn, EncoderReceiverData &dataOut);
    int getEncoderReceiverData(EncoderReceiverData &dataOut);
    int getEncoderReceiverData(int aliasIn, EncoderReceiverData &dataOut);//没加锁，可能coredump
    int resetMasterTimeMeasure();
    int resetMasterStatus();
    int writeTagData(int aliasIn, long long cardValueIn);
    int writeTagData(int aliasIn, QVector<unsigned char> cardValueIn);
    int getCurrentTagData(int aliasIn, long long &cardValueOut, bool &isCardDetected);
    int getCurrentTagData(int aliasIn, QVector<unsigned char> &cardValueOut, bool &isCardDetected);
    int getMaganeticSensorRawValue(int aliasIn, QVector<bool> &sensorRawValueOut);
    int getBatteryInfo_fromMotor(int aliasIn,BatteryInformation &batteryInfoOut);
    int getBatteryInfo(int aliasIn,BatteryInformation &batteryInfoOut);
    int controllerShutDown();
    int getEthercatDebugInfo(EthercatDebugInfo& debugInfo);
    int getCanDebugInfo(EthercatDebugInfo& debugInfo);
    int getModbusDebugInfo(bool isModbusRtu,int busIndex,EthercatDebugInfo& debugInfo);
    int getEthercatSlavesInformation(std::vector<EcatBusDevInfo_gsoap>& slavesInfo );
    bool isInitialOk();
    int initialMotorControlMode();
    //logicAxis QVector 线程安全问题，没有保护。
    int getMotorControlMode(int robID, int axisIndex, E_MOTOR_CONTROL_MODE &modeOut);
    int setMotorControlMode(int robID,int axisIndex,E_MOTOR_CONTROL_MODE modeIn);
    int stop();
    float getCycle();
    int getRobotDi(int robID, int index, bool& diOut);
    int getRobotAi(int robID,int index,double& aiOut);
    int getMaganeticDi(int robID,QVector<bool>& diOut);

    int init();//初始化机器人和设备

    //更新所有机器人是否有报警 (robID=-1=所有机器人)
    void checkError( int robID );

    //未标明(-1=所有机器人)的函数，不能传递-1参数
    EN_BATTERY_STATUS isRobotMotorBatteryOk(int robID, int axisId);//绝对值电池掉点



    //未标明(-1=所有机器人)的函数，不能传递-1参数
    bool clearMotorBatteryError(int robID);
    bool clearMotorBatteryErrorByAxis(int robID, int axisId);
    int clearMotorEncoderError_byNodeId(int nodeId);//清除绝对值编码器多圈错误。通过节点号，非别名
    int clearMotorEncoderError_byAlias(int aliasIn);


    int setEthercatMotorDcUserMode(int robID);//设置ＤＣ允许的时钟偏差

//    int setMotorControlMode(int robID, int axisId,E_MOTOR_CONTROL_MODE modeIn);
    int changeToHomingMode(int robID, int axisId, ZeroReturnParameter parameter);

    int changeToHomingMode(int robID, QVector<ZeroReturnParameter> parameter);

    int startGoZero(int robID, int axisId);

    int haltGoZero(int robID);

    int getZeroMovingStatus(int robID, int axisId, EM_ZERO_MOVING_STATUS &statusOut);

    int restorNormalOperationMode(int robID, int axisId);
    int restorNormalOperationMode(int robID);

    int setMotorTorqueLimit(int robID, int axisId, int positiveLimit,int negativeLimit);
    //2007-06h,unit is 0.01ms,3000 max
    bool setMotorTorqueFilterTime(int robID,int axisId, int filterTime);

    int setMotorZeroReturnParameter(int robID, int axisId,
                                     ZeroReturnParameter zeroReturnInfoIn);

    int readVersion(std::vector <ComponentVersion> &componentVersionList);
    /**
     * @brief servoOnRobot   //伺服使能 (robID=-1=所有机器人),有飞车可能
     * robCtl->isInitialOk()完成后，根据反馈位置，填充命令位置，
     * @param robID
     */
    bool servoOnRobot( int robID );
    bool servoOnRobotAxis( int robID ,int axisId);

    /**
     * @brief servoSwitch 伺服物理开关 按下/松开
     * @param robID 机器人id
     * @param flag  　ｏｎ＝ｔｒｕｅ
     */
    void servoSwitch( int robID , bool flag );

    /**
     * @brief servoOffRobot   ///关闭伺服  (robID=-1=所有机器人)
     * @param robID
     */
    void servoOffRobot( int robID );
    bool servoOffRobotAxis( int robID ,int axisId);

    /**
     * @brief quickStopRobot ///伺服立即停止  (robID=-1=所有机器人)
     * @param robID
     */
    void quickStopRobot( int robID );

    /**
     * @brief goHomeRobot ///归零(机器人所有轴)(相对方式) , (未实现)
     * @param robID
     * @return 0=false, 1=true;
     */
    int goHomeRobot( int robID );

//    /**
//     * @brief setHomeOffsetRobot  ///零点设定
//     * @param robID
//     * @param valueList
//     */
//    int setHomeOffsetRobot(int robID, QVector<int>&valueList );

    /**
         * @brief setControlWordRobot 写控制字 (robID=-1=所有机器人)
         * @param robID , -1=所有机器人
         * @param value 控制命令
         */
    void setControlWordRobot( int robID, int value );

    /**
     * @brief getServoDataRobot  ///获取轴的各种数据 statusWord errorcode
     * @param robID
     * @return
     */
    QVector<ServoState> getServoDataRobot( int robID );

    /**
     * @brief resetErrorRobot     ///报警复位 (robID=-1=所有机器人)
     * @param robID 机器人ID
     */
    int resetErrorRobot( int robID );

    /**
     * @brief clearMessage
     * @param msg
     * @return   , 0=ok
     */
    int clearMessage( Message msg );

    /**
        * @brief setAlias  写别名
        * @param node  节点
        * @param alias 具体的别名
        */
    int setAlias( int node , unsigned short alias );

    /**
         * @brief robotAxisToEthercatNode 获取指定轴的站号
         * @return 1 if ok
         */
    int robotAxisToEthercatNode(int robID, int axis, int &returnNode ,
                                E_DEVICE_PROTOCOL &protocolOut);
    int deviceAliasToEthercatNode(int deviceAliasIn, int &returnNode ,
                                E_DEVICE_PROTOCOL &protocolOut);

    /**
         * @brief isServoOnRobot   获取单个伺服 状态
         * @param robotId   id
         * Author:2017-1-17-xyf,添加单个机器人伺服ON（所有轴ON才正确）
         */
    bool isServoOnRobot( int robID );//伺服使能
    int  getServoOnStatus(int robID,QVector<bool> &flagReturn);
    bool isServoOnRobotAxis( int robID,int axisId );

    E_ECAT_MASTER_STATE getMasterState();


    //    /**
    //     * @brief homeParameterConfig 回零参数实时配置
    //     * @param robID  (-1=所有机器人)
    //     * @param methodList 回零方式
    //     * @param speedToSwitch ：到回零开关的速度
    //     * @param speedToZero ：到Z相脉冲的速度
    //     * @param accList ：回零加速度配置RobotControl robCtl;
    //     */
    //    void homeParameterConfig(
    //            int robID,
    //            QVector <quint8> methodList,
    //            QVector <int> speedToSwitch,
    //            QVector <int> speedToZero,
    //            QVector <int> accList );



    int getMotorErrorCode_by_sdo(int robID, int axisId, unsigned short &errorCodeOut);
    int getMotorVendorId(int robID, int axisId, unsigned int &vendorOut);
    int getMotorErrorCode(int robID, int axisId, unsigned short &errorCodeOut);

    int getMotorStatusWord(int robID, int axisId, unsigned short &statusWordOut);

    /**
     * @brief setMotorPositionRobot 写编码器的值
     * @param robID
     * @param vPos 编码器的值
     */
    void setMotorPositionRobot(int robID, QVector<int> vPos);

    /**
     * @brief getMotorPositionRobot  计算后的编码（带零点偏移）
     * @param robID
     * @return 编码器的值
     */
    QVector<int> getMotorPositionRobot( int robID );

    /**
     * @brief getMotorPositionRobot_real  读上来的真实编码器值 （真实编码器值）
     * @param robID
     * @return 编码器的值
     */
    QVector<int> getMotorPositionRobot_real( int robID );

    //    /**
    //     * @brief setAmpModeRobot //设置驱动模式 (robID=-1=所有机器人)
    //     * @param robID
    //     * @param mode 驱动器的模式
    //     */
    //    void setAmpModeRobot( int robID,  E_MOTOR_CMD mode );

    //    /**
    //     * @brief setServoDataRobot
    //     * @param robID
    //     */
    //    void setServoDataRobot(int robID );

    ///=======vrep control api========

    /**
     * @brief connectToVrep　连接模拟器
     * @param ip
     * @param _port　端口号
     * @return
     */
    int connectToVrep(QString _ip, int _port );

    /**
     * @brief disconnectFromVrep　断开连接
     */
    void disconnectFromVrep( );

    /**
     * @brief RobotControl::setIoSmiulationMode  io仿真模式
     * @param mode
     */
    void setIoSmiulationMode(int mode);
    /**
     * @brief RobotControl::setMotorSmiulationMode  motor仿真模式
     * @param mode
     */
    void setMotorSmiulationMode(int mode);
    int getSdo(int robID,
                  int axis
                  , int rObIndex
                  , int rObSubIndex
                  , LONG64 &rData
                  , int &rDataLen );
    int getSdoByNodeId(int nodeId
                  , int rObIndex
                  , int rObSubIndex
                  , LONG64 &rData
                  , int &rDataLen );
    int getSdoByAlias(int alias
                  , int rObIndex
                  , int rObSubIndex
                  , LONG64 &rData
                  , int &rDataLen );

    int  setSdo( int robID, int axis
                 ,int wObIndex
                 ,int wObSubIndex
                 ,LONG64 wData
                 ,int wDataLen  );
    int  setSdoByNodeId( int nodeId
                 ,int wObIndex
                 ,int wObSubIndex
                 ,LONG64 wData
                 ,int wDataLen  );
    int  setSdoByAlias( int alias
                 ,int wObIndex
                 ,int wObSubIndex
                 ,LONG64 wData
                 ,int wDataLen  );

    bool setDi(int robID, int index,bool valueIn);

private:
    int readDeviceUseageIniFile(QString filePath);
    bool readRobotsXmlAndInitialRobots( QString xmlfile ) ;
    bool readRobotInfoXml(int robID, QString xmlfile );
    /**
     * @brief addMsg  , 添加消息反馈
     */
    void addMsg(int messageLevel,
                 std::string componentName,
                 std::string messageType,
                 int messageCode,
                 int robotId,
                 int parameter1 = 0,
                 int parameter2 = 0,
                 int parameter3 = 0,
                 int parameter4 = 0 , QString messageInfo="");



public:
    QMap<int, RobotBase*> robotsMap;//<rovotId, RobotBase*>
    QMap<int, RobotBase*> robotsMap_onlyForCanbus;//<rovotId, RobotBase*>
    EcatBusManager* busManager;
    VrepControl* vrepCtl;
    EcatMasterBase* ecatmaster;
    QMap<int, VrepObject*> vobMap;//<rovotId, VrepObject*>

private:
    QVector<ModbusCom*> modbus_rtu_com;//预留支持多条bus
    QVector<ModbusCom*> modbus_tcp_com;//预留支持多条bus
    ModbusCom* tmpModbusCom;
    CanbusCom *canopenCom;
    EcatLog* log;

    int cycle_us;
    int cycle_ns;
    ComponentVersion versionInfo;

    int vrepRobotId;
    int ethercatLibType;
    bool isUseEthercatDeivce;
    bool isUseEthercatMotor;

    bool isUseModbusRtuDeivce;
    bool isUseModbusRtuMotor;

    bool isUseModbusTcpDeivce;
    bool isUseModbusTcpMotor;

    bool isUseCanopenDevice;
    bool isUseCanopenMotor;




};



#endif // robotcontrol_H
